﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Threading.Tasks;

namespace PowerStation.AppCode
{
    /// <summary>
    /// 开启Jwt认证
    /// </summary>
    public static class AuthorizationSetup
    {
        private static JwtSecurityTokenHandler JwtManager = new JwtSecurityTokenHandler();
        /// <summary>
        /// 开启认证
        /// </summary>
        /// <param name="services"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void AddAuthorizationSetup(this IServiceCollection services, IConfiguration configuration)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            // 配置策略授权
            services.AddAuthorization(o =>
            {
                //foreach (RoleType item in Enum.GetValues(typeof(RoleType)))
                //{
                //    o.AddPolicy(item.ToString(), k => { k.RequireRole(item.ToString()); });
                //}
            });

            string key = configuration["JwtSettings:SecurityKey"];//Appsettings.app(new string[] { "JwtSettings", "SecurityKey" });
            string issuer = configuration["JwtSettings:Issuer"];//Appsettings.app(new string[] { "JwtSettings", "Issuer" });
            string audience = configuration["JwtSettings:Audience"];//Appsettings.app(new string[] { "JwtSettings", "Audience" });

            SecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)); //秘钥的长度有要求，必须>=16位
            
            services.AddAuthentication("Bearer").AddJwtBearer(o =>
            {
                o.TokenValidationParameters = new TokenValidationParameters()
                {
                    //是否秘钥认证
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = securityKey, //秘钥

                    //是否验证发行人
                    ValidateIssuer = true,
                    ValidIssuer = issuer, //这个字符串可以随便写，就是发行人

                    //是否验证订阅
                    ValidateAudience = true,
                    ValidAudience = audience,

                    //是否验证过期时间
                    RequireExpirationTime = true,
                    ValidateLifetime = true,
                };
                o.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents() {
                    OnMessageReceived = ctx => {
                        if (ctx.HttpContext.Request.Path.Value.Contains("/Login/GetJwtToken")) return Task.CompletedTask;
                        if (ctx.HttpContext.Request.Headers.ContainsKey("authorization")) return Task.CompletedTask;
                        string tokenStr = ctx.HttpContext.Request.Cookies["auth"];

                        if (!string.IsNullOrEmpty(tokenStr))
                        {
                            try
                            {
                                SecurityToken token;
                                var pm = JwtManager.ValidateToken(tokenStr, o.TokenValidationParameters, out token);
                                // Validate token
                                if (pm != null)
                                {

                                    // Set the principal
                                    // Will throw error if not set
                                    ctx.Principal = pm;

                                    // Tells ASP.NET that the authentication was successful
                                    ctx.Success();

                                    // Add the principal to the HttpContext for easy access in any the controllers (only routes that are authenticated)
                                    ctx.HttpContext.Items.Add("claims", pm);
                                }
                            }
                            catch (Exception ex) {
                                ctx.Fail(ex);
                            }
                        }
                        return Task.CompletedTask;
                    }
                };
                    
            });
        }
    }
}
